home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
psi110g.zip
/
LAPBTIME.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
5KB
|
180 lines
/* LAPB (AX.25) timer recovery routines
* Copyright 1991 Phil Karn, KA9Q
*
* Mods by G1EMM
*/
#include "global.h"
#ifdef AX25
#include "mbuf.h"
#include "ax25.h"
#include "timer.h"
#include "lapb.h"
#ifdef NETROM
#include "netrom.h"
#endif
static void tx_enq __ARGS((struct ax25_cb *axp));
int lapbtimertype = 0; /* default to binary exponential */
/* Called whenever timer T1 expires */
void
recover(p)
void *p;
{
struct ax25_cb *axp = (struct ax25_cb *)p;
long waittime = dur_timer(&axp->t1);
axp->flags.retrans = 1;
axp->retries++;
#ifdef NETROM
{
struct nrnbr_tab *np;
/* If this is a netrom neighbour, increment the retry count */
if((axp->iface->flags & IS_NR_IFACE) && ((np = find_nrnbr(axp->remote,axp->iface)) != NULL))
np->retries++;
}
#endif
switch(axp->iface->ax25->lapbtimertype){
case 2: /* original backoff mode*/
waittime = axp->srt * 2;
break;
case 1: /* linear backoff mode */
if((1L << axp->retries) < axp->iface->ax25->blimit)
waittime = dur_timer(&axp->t1) + axp->srt;
break;
case 0: /* exponential backoff mode */
if((1L << axp->retries) < axp->iface->ax25->blimit)
waittime = dur_timer(&axp->t1) * 2;
break;
}
{
/* IF a maximum is set, and we surpass it, use the maximum */
long maxwait = axp->iface->ax25->maxwait;
if(maxwait && (waittime > maxwait))
waittime = maxwait;
}
set_timer(&axp->t1,waittime);
switch(axp->state){
case LAPB_SETUP:
if(axp->n2 != 0 && axp->retries > axp->n2){
#ifdef NETROM
nr_derate(axp);
#endif
free_q(&axp->txq);
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
sendctl(axp,LAPB_COMMAND,SABM|PF);
start_timer(&axp->t1);
}
break;
case LAPB_DISCPENDING:
if(axp->n2 != 0 && axp->retries > axp->n2){
#ifdef NETROM
nr_derate(axp);
#endif
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
sendctl(axp,LAPB_COMMAND,DISC|PF);
start_timer(&axp->t1);
}
break;
case LAPB_CONNECTED:
case LAPB_RECOVERY:
if(axp->n2 != 0 && axp->retries > axp->n2){
/* Give up */
#ifdef NETROM
nr_derate(axp);
#endif
sendctl(axp,LAPB_RESPONSE,DM|PF);
free_q(&axp->txq);
axp->reason = LB_TIMEOUT;
lapbstate(axp,LAPB_DISCONNECTED);
} else {
/* Transmit poll */
tx_enq(axp);
lapbstate(axp,LAPB_RECOVERY);
}
break;
}
}
/* Send a poll (S-frame command with the poll bit set) */
void
pollthem(p)
void *p;
{
register struct ax25_cb *axp;
axp = (struct ax25_cb *)p;
if(axp->proto == V1)
return; /* Not supported in the old protocol */
switch(axp->state){
case LAPB_CONNECTED:
axp->retries = 0;
tx_enq(axp);
lapbstate(axp,LAPB_RECOVERY);
break;
}
}
/* Called whenever timer T4 (link rudundancy timer) expires */
void
redundant(p)
void *p;
{
register struct ax25_cb *axp;
axp = (struct ax25_cb *)p;
switch(axp->state){
case LAPB_CONNECTED:
case LAPB_RECOVERY:
axp->retries = 0;
sendctl(axp,LAPB_COMMAND,DISC|PF);
start_timer(&axp->t1);
free_q(&axp->txq);
lapbstate(axp,LAPB_DISCPENDING);
break;
}
}
/* Transmit query */
static void
tx_enq(axp)
register struct ax25_cb *axp;
{
char ctl;
struct mbuf *bp;
/* I believe that retransmitting the oldest unacked
* I-frame tends to give better performance than polling,
* as long as the frame isn't too "large", because
* chances are that the I frame got lost anyway.
* This is an option in LAPB, but not in the official AX.25.
*/
if(axp->txq != NULLBUF
&& (len_p(axp->txq) < axp->pthresh || axp->proto == V1)){
/* Retransmit oldest unacked I-frame */
dup_p(&bp,axp->txq,0,len_p(axp->txq));
ctl = PF | I | (((axp->vs - axp->unack) & MMASK) << 1)
| (axp->vr << 5);
sendframe(axp,LAPB_COMMAND,ctl,bp);
} else {
ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;
sendctl(axp,LAPB_COMMAND,ctl);
}
axp->response = 0;
stop_timer(&axp->t3);
start_timer(&axp->t1);
}
#endif /* AX25 */